package graphics.rendering.shaders;

import java.io.BufferedReader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import util.common.AbstractManager;

/**
 * Manages loading and binding of shader programs.
 * @author Joel Rausch
 */
public class ShaderManager extends AbstractManager {

	/**
	 * Map of names to shader.
	 */
	private final Map<String, ShaderProgram> shaders =
			new HashMap<String, ShaderProgram>();

	@Override
	public void startup() throws Exception {
		parent.files.addSearchPath(new String[] {"res", "shaders"});
		useShader("debug");
	}

	@Override
	public void shutdown() throws Exception {
		Iterator<ShaderProgram> iter = shaders.values().iterator();
		while(iter.hasNext()) {
			iter.next().destroy();
			iter.remove();
		}
	}
	
	/**
	 * Lazily load and bind shader.
	 * @param shaderName
	 * @throws Exception
	 */
	public void useShader(String shaderName) throws Exception {
		ShaderProgram shader = shaders.get(shaderName);
		
		// Lazily load
		if(shader == null) {
			StringBuilder vertSource = new StringBuilder();
			StringBuilder fragSource = new StringBuilder();
			BufferedReader reader;
			
			// Load vertex shader source file
			reader = parent.files.textReader(shaderName + ".vert");
			for(;;) {
				String line = reader.readLine();
				if(line != null) {
					vertSource.append(line);
					vertSource.append("\n");
				} else {
					break;
				}
			}
			reader.close();
			
			// Load fragment shader source file
			reader = parent.files.textReader(shaderName + ".frag");
			for(;;) {
				String line = reader.readLine();
				if(line != null) {
					fragSource.append(line);
					fragSource.append("\n");
				} else {
					break;
				}
			}
			reader.close();
			
			// Create shader program
			shader = new ShaderProgram(vertSource.toString(), fragSource.toString());
		}
		
		shader.bindShader();
	}
}
